﻿using System.Collections.Generic;
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.IO;

namespace Ramparts
{

    public class World : GameComponent
    {
        
        public TileGrid groundLayer;
        public TileGrid wallLayer;
        public TileGrid buildingLayer;
        public bool newWorld;

        public WorldHelper worldHelper;

        public List<GameComponent> enemyList;
 
        private Player players;
        GraphicsDeviceManager graphics;
        public Ramparts rampart;
        
        // The Lowest Grid Width and Height
        public int baseGridWidth;
        public int baseGridHeight;

        // The lowest grid cell width and height
        public int baseCellWidth;
        public int baseCellHeight;

        // The total world size in Pixels
        public int worldHeight;
        public int worldWidth;

        public bool isometricView;

        // Sheets
        private SpriteSheet groundSheet;
        private SpriteSheet tetrisSheet;
        private SpriteSheet buildingSheet;
        private SpriteSheet isoSheet;
        private SpriteSheet isoObjectSheet;
        private int[,] wallMask;
        public static bool maskChanged;

        public enum TileName : int
        {
            empty = 0,
            GreenLight = 1,
            GreenDark = 2,
            Water = 9,
            GreenDarkTransitionWaterBottom = 10,
            GreenLightTransitionWaterBottom = 11,
            GreenDarkTransitionWaterTop = 12,
            GreenLightTransitionWaterTop = 13,
            GreenDarkTransitionWaterRight = 14,
            GreenLightTransitionWaterRight = 15,
            GreenDarkTransitionWaterLeft = 16,
            GreenLightTransitionWaterLeft =17,
            GreenDarkTransitionAngleJoinWaterBottomRight = 18,
            GreenLightTransitionAngleJoinWaterBottomRight = 19,
            GreenDarkTransitionAngleWaterBottomRight = 20,
            GreenLightTransitionAngleWaterBottomRight = 21,
            GreenDarkTransitionAngleJoinWaterTopLeft = 22,
            GreenLightTransitionAngleJoinWaterTopLeft = 23,
            GreenDarkTransitionAngleWaterTopLeft = 24,
            GreenLightTransitionAngleWaterTopLeft = 25,
            GreenDarkTransitionAngleJoinWaterTopRight = 26,
            GreenLightTransitionAngleJoinWaterTopRight = 27,
            GreenDarkTransitionAngleWaterTopRight = 28,
            GreenLightTransitionAngleWaterTopRight = 29,
            GreenDarkTransitionAngleJoinWaterBottomLeft = 30,
            GreenLightTransitionAngleJoinWaterBottomLeft = 31,
            GreenDarkTransitionAngleWaterBottomLeft = 32,
            GreenLightTransitionAngleWaterBottomLeft = 33



        }

        public enum WallTiles : int
        {
            empty = 0,
            UpperLeftCorner = 1,
            WallLeftRight = 2,
            UpperRightCorner = 3,
            BottomLeftCorner = 4,
            BottomRightCorner = 5,
            RightEnd = 6,
            LeftEnd = 7,
            TopLeftBottom = 8,
            TopRightBottom = 9,
            LeftBottomRight = 10,
            LeftTopRight = 11,
            WallTopBottom = 12,
            EndBottom = 13,
            EndTop = 14,
            Single = 15,
            FourSides = 16
        }

        public World(Ramparts rampart, int worldWidth, int worldHeight, int baseTileHeight, int baseTileWidth)
        {

            graphics = rampart.graphics;

            this.rampart = rampart;
            baseGridHeight = worldWidth / baseTileWidth;
            baseGridWidth = worldHeight / baseTileHeight;
            this.worldHeight = worldHeight;
            this.worldWidth = worldWidth;
            
            setWorldTextures();
            setWorldGrids();
            players = new Player(); 

            enemyList = new List<GameComponent>();
        
        }


        public World(Ramparts rampart, string fileName)
        {


        
            graphics = rampart.graphics;

            enemyList = new List<GameComponent>();

            players = new Player();

            // Generate a default game board from a file
            StreamReader sr = new StreamReader(fileName);
            string input = sr.ReadLine();
            string[] tilesFromRead;
            int row = 0;

            this.rampart = rampart;
            worldWidth = 800;
            worldHeight = 600;
            baseGridHeight = worldWidth / 20;
            baseGridWidth = worldHeight / 20;
            baseCellWidth = 20;
            baseCellHeight = 20;

            setWorldTextures();
            setWorldGrids();
       
            wallLayer.isometricSheet = isoSheet;
            buildingLayer.isometricSheet = isoObjectSheet;
       
            while (!input.Equals("CASTLES"))
            {
                tilesFromRead = input.Split(' ');

                for (int col = 0; col < tilesFromRead.Length -1; col++)
                {
                    // Console.WriteLine("setting tile at: " + tilesFromRead.Length + " " + col + "," + row);
                    groundLayer.SetTile(col, row, Convert.ToInt32(tilesFromRead[col]));
                    wallLayer.SetTile(new Vector2(col,row), 0);
                    buildingLayer.SetTile(new Vector2(col,row),0);
                }
                row++;
                input = sr.ReadLine();
            }
            input = sr.ReadLine();
            while (input != null)
            {
                string[] parts = input.Split(',');
                setCastle(Convert.ToInt32(parts[0]), Convert.ToInt32(parts[1]));
                input = sr.ReadLine();
            }


        }

        public void setWorldGrids()
        {
            newWorld = true;
            
            // Define the groundLayer
            groundLayer = new TileGrid(
                20,
                20,
                baseGridHeight,
                baseGridWidth,
                Vector2.Zero,
                groundSheet,
                graphics,
                rampart.sceneManager);

            // HACK
            Texture2D tetrisTexture = rampart.Content.Load<Texture2D>("Content\\tetris_tiles_placed");
            AnimatedTile tile = new AnimatedTile(tetrisTexture, 3);
            tile.addFrame(new Rectangle(0, 20, 20, 20));
            tile.addFrame(new Rectangle(20, 20, 20, 20));
            tile.addFrame(new Rectangle(40,20,20,20));

            // groundLayer.animatedTiles.Add(9, tile);

            // Define the wallLayer
            wallLayer = new TileGrid(
                20,
                20,
                baseGridHeight,
                baseGridWidth,
                Vector2.Zero,
                tetrisSheet,
                graphics,
                rampart.sceneManager);

            // Make the mask for drawing the player surrounded are
            wallMask = new int[baseGridHeight,baseGridWidth];


            // Define the wallLayer
            buildingLayer = new TileGrid(
                20,
                20,
                baseGridHeight,
                baseGridWidth,
                Vector2.Zero,
                buildingSheet,
                graphics,
                rampart.sceneManager);


        }

        public void setWorldTextures()
        {

            Texture2D groundTexture = rampart.Content.Load<Texture2D>("Content\\classic_tiles");
            Texture2D tetrisTexture = rampart.Content.Load<Texture2D>("Content\\tetris_tiles_placed");
            Texture2D buildingTexture = rampart.Content.Load<Texture2D>("Content\\object_tiles");
            Texture2D isoTexture = rampart.content.Load<Texture2D>("Content\\iso_tiles");
            Texture2D isoObjectTexture = rampart.content.Load<Texture2D>("Content\\iso_objects");

            // Set Up Tiles
            groundSheet = new SpriteSheet(groundTexture);
            tetrisSheet = new SpriteSheet(tetrisTexture);
            buildingSheet = new SpriteSheet(buildingTexture);
            isoSheet = new SpriteSheet(isoTexture);
            isoObjectSheet = new SpriteSheet(isoObjectTexture);

          

            // 2D Castle
            isoObjectSheet.AddSourceSprite(1, new Rectangle(0, 0, 20, 20));
            isoObjectSheet.AddSourceSprite(2, new Rectangle(0, 20, 20, 20));
            isoObjectSheet.AddSourceSprite(3, new Rectangle(20, 0, 20, 20));
            isoObjectSheet.AddSourceSprite(4, new Rectangle(20, 20, 20, 20));
           
            // 2D Canon 
            isoObjectSheet.AddSourceSprite(5, new Rectangle(40, 0, 20, 20));
            isoObjectSheet.AddSourceSprite(6, new Rectangle(60, 0, 20, 20));
            isoObjectSheet.AddSourceSprite(7, new Rectangle(40, 20, 20, 20));
            isoObjectSheet.AddSourceSprite(8, new Rectangle(60, 20, 20, 20));

            // ISO Castle 
            buildingSheet.AddSourceSprite(1,
              new Rectangle(0, 0, 20, 20));
            buildingSheet.AddSourceSprite(2,
              new Rectangle(0, 20, 20, 20));
            buildingSheet.AddSourceSprite(3,
              new Rectangle(20, 0, 20, 20));
            buildingSheet.AddSourceSprite(4,
              new Rectangle(20, 20, 20, 20));
          
            // Iso Canon
            buildingSheet.AddSourceSprite(5,
                new Rectangle(40, 0, 20, 20));
            buildingSheet.AddSourceSprite(6,
                new Rectangle(60, 0, 20, 20));
            buildingSheet.AddSourceSprite(7,
                new Rectangle(40, 20, 20, 20));
            buildingSheet.AddSourceSprite(8,
                new Rectangle(60, 20, 20, 20));

            // Wall Pieces
            // TODO RENAME THIS TO WALL PIECES NOT TETRIS PIECES (WALL_PIECES 2D)
            isoSheet.AddSourceSprite((int)WallTiles.UpperLeftCorner,
                new Rectangle(0, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.WallLeftRight,
                new Rectangle(20, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.UpperRightCorner,
                new Rectangle(40, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.BottomLeftCorner,
                new Rectangle(60, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.BottomRightCorner,
                new Rectangle(80, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.RightEnd,
                new Rectangle(100, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.LeftEnd,
                new Rectangle(120, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.TopLeftBottom,
                new Rectangle(140, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.TopRightBottom,
                new Rectangle(160, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.LeftBottomRight,
                new Rectangle(180, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.LeftTopRight,
                new Rectangle(200, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.WallTopBottom,
               new Rectangle(220, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.EndBottom,
                new Rectangle(240, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.EndTop,
                new Rectangle(260, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.Single,
                new Rectangle(280, 0, 20, 39));
            isoSheet.AddSourceSprite((int)WallTiles.FourSides,
                new Rectangle(300, 0, 20, 39));

            // Surround Colors
            isoSheet.AddSourceSprite(54, new Rectangle(0, 50, 20, 20)); // DARK BLUE
            isoSheet.AddSourceSprite(55, new Rectangle(0, 50, 20, 20)); // LIGHT BLUE


            // Wall Pieces
            // TODO RENAME THIS TO WALL PIECES NOT TETRIS PIECES (WALL_PIECES 2D)
            tetrisSheet.AddSourceSprite((int)WallTiles.UpperLeftCorner,
                new Rectangle(0, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.WallLeftRight,
                new Rectangle(20, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.UpperRightCorner,
                new Rectangle(40, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.BottomLeftCorner,
                new Rectangle(60, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.BottomRightCorner,
                new Rectangle(80, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.RightEnd,
                new Rectangle(100, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.LeftEnd,
                new Rectangle(120, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.TopLeftBottom,
                new Rectangle(140, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.TopRightBottom,
                new Rectangle(160, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.LeftBottomRight,
                new Rectangle(180, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.LeftTopRight,
                new Rectangle(200, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.WallTopBottom,
               new Rectangle(220, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.EndBottom,
                new Rectangle(240, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.EndTop,
                new Rectangle(260, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.Single,
                new Rectangle(280, 0, 20, 20));
            tetrisSheet.AddSourceSprite((int)WallTiles.FourSides,
                new Rectangle(300, 0, 20, 20));


            // DOUG THESE ARE YOUR GRIDS FOR YOUR GAME
            // RED, BLUE AND PURPLE INCLUDED
            tetrisSheet.AddSourceSprite(50, new Rectangle(40, 20, 20, 20)); // DARK RED
            tetrisSheet.AddSourceSprite(51, new Rectangle(60, 20, 20, 20)); // LIGHT RED

            tetrisSheet.AddSourceSprite(52, new Rectangle(80, 20, 20, 20)); // DARK PURPLE
            tetrisSheet.AddSourceSprite(53, new Rectangle(100, 20, 20, 20)); // LIGHT PURPLE

            tetrisSheet.AddSourceSprite(54, new Rectangle(120, 20, 20, 20)); // DARK BLUE
            tetrisSheet.AddSourceSprite(55, new Rectangle(140, 20, 20, 20)); // LIGHT BLUE



            #region Ground Sheet init

            groundSheet.AddSourceSprite((int)TileName.GreenDark,
                new Rectangle(160, 20, 20, 20));
            
            groundSheet.AddSourceSprite((int)TileName.GreenLight,
                new Rectangle(180, 20, 20, 20));
            
            groundSheet.AddSourceSprite((int)TileName.Water,
                new Rectangle(0, 0, 20, 20));
            
            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionWaterBottom,
                new Rectangle(20, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionWaterBottom,
                new Rectangle(40, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionWaterTop,
                new Rectangle(60, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionWaterTop,
                new Rectangle(80, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionWaterRight,
                new Rectangle(100, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionWaterRight,
                new Rectangle(120, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionWaterLeft,
                new Rectangle(140, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionWaterLeft,
                new Rectangle(160, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionAngleJoinWaterBottomRight,
                new Rectangle(180, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionAngleJoinWaterBottomRight,
                new Rectangle(200, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionAngleWaterBottomRight,
                new Rectangle(220, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionAngleWaterBottomRight,
                new Rectangle(240, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionAngleJoinWaterTopLeft,
                new Rectangle(260, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionAngleJoinWaterTopLeft,
                new Rectangle(280, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionAngleWaterTopLeft,
                new Rectangle(300, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionAngleWaterTopLeft,
                new Rectangle(320, 0, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionAngleJoinWaterTopRight,
                new Rectangle(0, 20, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionAngleJoinWaterTopRight,
                new Rectangle(20, 20, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionAngleWaterTopRight,
                new Rectangle(40, 20, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionAngleWaterTopRight,
                new Rectangle(60, 20, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionAngleJoinWaterBottomLeft,
                new Rectangle(80, 20, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionAngleJoinWaterBottomLeft,
                new Rectangle(100, 20, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenDarkTransitionAngleWaterBottomLeft,
                new Rectangle(120, 20, 20, 20));

            groundSheet.AddSourceSprite((int)TileName.GreenLightTransitionAngleWaterBottomLeft,
                new Rectangle(140, 20, 20, 20));


            #endregion
        }

        public void drawEnemies()
        {
            foreach (GameComponent component in enemyList)
            {
                component.Draw();
            }
        }

        public void updateEnemies(GameTime gameTime)
        {
            foreach (GameComponent component in enemyList)
            {
                component.Update(gameTime);
            }
                
        }

        public override void Update(GameTime gameTime)
        {
            // this needs to change to an array
                this.groundLayer.Update(gameTime);
                updateEnemies(gameTime);
        }

        public override void Draw()
        {

            if (!isometricView)
            {
                // Draws ground objects
                groundLayer.Draw();
                wallLayer.Draw();
                buildingLayer.Draw();
                
            }
            else
            {

                // We have to manually draw each grid because of isometric issues....
                // is there a better way to do this?
                //groundLayer.Draw();

                for (int y = 0; y < worldHeight; y = y + baseCellHeight)
                {
                    for (int x = 0; x < worldWidth; x = x + baseCellWidth)
                    {
                        groundLayer.DrawTile(groundLayer.onTile(new Vector2(x, y)));
                        wallLayer.DrawTile(wallLayer.onTile(new Vector2(x, y)));
                        buildingLayer.DrawTile(buildingLayer.onTile(new Vector2(x, y)));
                    }
                }
            }
            drawEnemies();
        }

        public void ClearWallMask()
        {
            for (int row = 0; row < wallLayer.gridWidth; row++)
            {
                for (int col = 0; col < wallLayer.gridHeight; col++)
                {
                    wallMask[row, col] = 0;
                }
            }
        }

        /// <summary>
        /// Call this if you need to check if walls are connected
        /// </summary>
        public void ConnectWalls()
        {
            for (int x = 0; x < wallLayer.gridWidth; x++)
            {
                for (int y = 0; y < wallLayer.gridHeight; y++)
                {
                    if (wallMask[x,y] == 1)
                    {
                        wallLayer.SetTile(new Vector2(x,y), FindWallIndex(x,y));
                    }
                }

            }

        }

        /// <summary>
        /// Used to find if this wall has any connections and returns the 
        /// index for the appropriate tile
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public int FindWallIndex(int x, int y)
        {
            int indexSum = 0;
            if (x != 0)
            {
                if (wallMask[x - 1, y] == 1)
                {
                    indexSum += 1;
                }
            }
            if (x != wallLayer.gridWidth - 1)
            {
                if (wallMask[x + 1, y] == 1)
                {
                    indexSum += 2;
                }
            }
            if (y != 0)
            {
                if (wallMask[x, y - 1] == 1)
                {
                    indexSum += 4;
                }
            }
            if (y != wallLayer.gridHeight -1)
            {
                if (wallMask[x, y +1] ==1)
                {
                    indexSum += 8;
                }
            }
            switch (indexSum)
            {
                case 1:
                    return (int)WallTiles.RightEnd; // This return should be the index for an end at the right
                case 2:
                    return (int)WallTiles.LeftEnd; // This return should be the index for an end at the Left
                case 3:
                    return (int)WallTiles.WallLeftRight; // This return should be the index for a straight left to right
                case 4:
                    return (int)WallTiles.EndBottom; // end at the bottom
                case 5:
                    return (int)WallTiles.BottomRightCorner; // bottom right corner
                case 6:
                    return (int)WallTiles.BottomLeftCorner; // bottom left corner
                case 7:
                    return (int)WallTiles.LeftTopRight; // connected at left right and top
                case 8:
                    return (int)WallTiles.EndTop; // end at the top
                case 9:
                    return (int)WallTiles.UpperRightCorner; // upper right corner
                case 10:
                    return (int)WallTiles.UpperLeftCorner; // upper left corner
                case 11:
                    return (int)WallTiles.LeftBottomRight; // connected left right and bottom
                case 12:
                    return (int)WallTiles.WallTopBottom; // connected top to bottom
                case 13:
                    return (int)WallTiles.TopLeftBottom; // connected top to bottom and left
                case 14:
                    return (int)WallTiles.TopRightBottom; // connected top to bottom and right
                case 15:
                    return (int)WallTiles.FourSides; // connected on all sides
                default:
                    return (int)WallTiles.Single; // single wall on it's own
            }
                



        }

        /// <summary>
        /// This is the main method we can call to do all the checking
        /// </summary>
        public void CheckIfSurrounded()
        {
            ClearWallMask();
            
            for (int i = 0; i < wallLayer.gridWidth; i++)
            {
                for (int j = 0; j < wallLayer.gridHeight; j++)
                {
                    CheckSurrounded(i, j);
                }
            }
            do
            {
                maskChanged = false;
                for (int i = 0; i < wallLayer.gridWidth; i++)
                {
                    for (int j = 0; j < wallLayer.gridHeight; j++)
                    {
                        DoubleCheckMask(i, j);
                    }
                }
            } while (maskChanged);

        }


        /// <summary>
        /// This cleans up my mess.  this will check for tiles that need to be clear.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        private void DoubleCheckMask(int x, int y)
        {
            if (x != 0 && x != wallLayer.gridWidth - 1 && y != 0 && y != wallLayer.gridHeight - 1)
            {

                if (wallMask[x, y] != 1)
                {
                    if (wallMask[x - 1, y] == 9 || wallMask[x, y - 1] == 9 ||
                        wallMask[x, y + 1] == 9 || wallMask[x + 1, y] == 9 ||
                        wallMask[x - 1, y - 1] == 9 || wallMask[x - 1, y + 1] == 9 ||
                        wallMask[x + 1, y - 1] == 9 || wallMask[x + 1, y + 1] == 9)
                    {
                        if (wallMask[x, y] != 9)
                        {
                            wallMask[x, y] = 9;
                            maskChanged = true;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// This is the sub function that checks every tile and assigns the edges 9's and walls 1's
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public int CheckSurrounded(int x, int y)
        {
            if (wallMask[x, y] == 0 || wallMask[x, y] == 2)
            {
                if (wallLayer.getGridValueAt(x,y) > 0 && 
                    wallLayer.getGridValueAt(x,y) < 17)
                {
                    wallMask[x, y] = 1;
                    return 1;
                }

                else if  ((x == 0 || x == wallLayer.gridWidth - 1 || 
                     y == 0 || y == wallLayer.gridHeight - 1) && wallMask[x,y] != 1) 
                {
                    wallMask[x, y] = 9;
                    return 9;
                }
                else
                { 
                    wallMask[x, y] = 2;
                    return 2;
                }

            }
            return wallMask[x, y];

        }

        public void DrawPlayerMask()
        {
            for (int x = 0; x < wallLayer.gridWidth; x++)
            {
                for (int y = 0; y < wallLayer.gridHeight; y++)
                {
                    if (wallMask[x, y] == 2)
                    {
                        wallLayer.SetTile(new Vector2(x, y), groundLayer.getGridValueAt(x,y) +53);
                    }
                    if (wallMask[x, y] == 9)
                    {
                        wallLayer.SetTile(new Vector2(x, y), 0);
                    }
                }
            }
        }

        public bool CanPlaceCannon(int playerIndex)
        {
            if (players.numOfCannons < players.maxCannons)
            {
                return true;
            }

            return false;

        }

        public bool PlaceCannon(int playerIndex, Vector2 position)
        {
            Vector2 wallPosition = wallLayer.onTile(position);
            Vector2 buildingPosition = buildingLayer.onTile(position);
            for (int x = 0; x < 2; x++)
            {
                for (int y = 0; y < 2; y++)
                {

                    if (buildingLayer.getGridValueAt(new Vector2(buildingPosition.X + x, 
                                                                 buildingPosition.Y + y)) > 0)
                    {
                        Console.WriteLine("Building Colision");
                        return false;
                    }
                    if (wallLayer.getGridValueAt(new Vector2(wallPosition.X +x, wallPosition.Y +y)) < 54 ||
                        wallLayer.getGridValueAt(new Vector2(wallPosition.X + x, wallPosition.Y + y)) > 55)
                    {
                        Console.WriteLine("Not on Player Color {0}:{1} is Value {2}", wallPosition.X, wallPosition.Y, wallLayer.getGridValueAt(new Vector2(wallPosition.X +x, wallPosition.Y +y)));
                        return false;
                    }
                }
            }
            buildingLayer.SetTile(buildingPosition,5);
            buildingLayer.SetTile((int)buildingPosition.X + 1, (int)buildingPosition.Y, 6);
            buildingLayer.SetTile((int)buildingPosition.X, (int)buildingPosition.Y + 1, 7);
            buildingLayer.SetTile((int)buildingPosition.X + 1, (int)buildingPosition.Y + 1, 8);
            
            players.numOfCannons++;
            return true;
        }


        public void setCastle(int x, int y)
        {
            buildingLayer.SetTile(x, y-1, 1);
            buildingLayer.SetTile(x + 1, y-1, 3);
            buildingLayer.SetTile(x, y, 2);
            buildingLayer.SetTile(x + 1, y, 4);

        }

        public bool GetScore(int playerIndex)
        {
            bool playerHasCastle = false;
            int playerRoundScore = 0;

            if (playerIndex == 0)
            {
                for (int x = 0; x < wallLayer.gridWidth; x++)
                {
                    for (int y = 0; y < wallLayer.gridWidth; y++)
                    {
                        if (wallLayer.getGridValueAt(x, y) == 54 || wallLayer.getGridValueAt(x, y) == 55)
                        {
                            playerRoundScore += 10;
                            if (buildingLayer.getGridValueAt(x, y) == 1)
                            {
                                playerHasCastle = true;
                                playerRoundScore += 1;
                            }
                        }

                    }
                }
            }
            players.score += playerRoundScore;
            return playerHasCastle;
        }

        
        
        public  bool putDownPiece(TetrisPiece piece, Vector2 position)
        {

            Vector2 wallPosition = wallLayer.onTile(position);
            Vector2 buildingPosition = buildingLayer.onTile(position);
            Vector2 groundPosition = groundLayer.onTile(position);

            Console.WriteLine(buildingPosition);

            for (int x = 0; x < 4; x++)
            {
                for (int y = 0; y < 4; y++)
                {
                    buildingPosition = buildingLayer.onTile(new Vector2(position.X + (20 * x) , position.Y + (20 * y)));
                    if (buildingLayer.getGridValueAt(buildingPosition) > 0 && piece.currentBlock[x, y] > 0)
                    {
                        Console.WriteLine("building collision");
                        return false;
                    }
                    if (wallLayer.getGridValueAt(new Vector2( wallPosition.X + x, wallPosition.Y +y)) == -1 && piece.currentBlock[x,y] >0)
                        return false;
                    
                    if (wallLayer.getGridValueAt(new Vector2(wallPosition.X + x, wallPosition.Y + y)) > 0 &&
                        wallLayer.getGridValueAt(new Vector2(wallPosition.X + x, wallPosition.Y + y)) < 17 &&
                        piece.currentBlock[x, y] > 0)
                        return false;
                    //TODO make check for if it is on pure land tile
                    if (groundLayer.getGridValueAt(new Vector2(groundPosition.X + x, groundPosition.Y + y)) > 0 &&
                        groundLayer.getGridValueAt(new Vector2(groundPosition.X + x, groundPosition.Y + y)) > 3 &&
                        piece.currentBlock[x, y] > 0)
                        return false;
                    
                }
            }


            for (int x = 0; x < 4; x++)
            {

                for (int y = 0; y < 4; y++)
                {
                    if (piece.currentBlock[x, y] != 0)
                    {
                        wallLayer.SetTile(new Vector2(wallPosition.X + x, wallPosition.Y + y), 1);
                    }

                }
            }

            Console.WriteLine("Block Down");
            CheckIfSurrounded();
            DrawPlayerMask();
            ConnectWalls();



            return true;
        }

        public void setIso()
        {
            Console.WriteLine("Isometric View");
            isometricView = true;
            wallLayer.useAlternateSpriteSheet();
            buildingLayer.useAlternateSpriteSheet();
        }

        public void set2d()
        {
            Console.WriteLine("2D View");
            isometricView = false;
            wallLayer.useMainSpriteSheet();
            buildingLayer.useMainSpriteSheet();
        }


    }

}
   
